package com.nut.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nut.article.api.req.UpdatePasswordReq;
import com.nut.article.api.resp.MenuVo;
import com.nut.article.api.resp.UserInfoResp;
import com.nut.article.common.Holder;
import com.nut.article.common.Result;
import com.nut.article.config.RsaProperties;
import com.nut.article.entity.SysMenu;
import com.nut.article.entity.SysUser;
import com.nut.article.entity.SysUserRole;
import com.nut.article.interceptor.UserJwt;
import com.nut.article.mapper.SysMenuMapper;
import com.nut.article.mapper.SysUserMapper;
import com.nut.article.mapper.SysUserRoleMapper;
import com.nut.article.service.SysUserService;
import com.nut.article.util.RsaUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public Result<IPage<SysUser>> list(String username, String mobile, String deptCode, Integer status, Integer pageNo, Integer pageSize) {
        Page<SysUser> page = new Page<>();
        page.setSize(pageSize);
        page.setCurrent(pageNo);

        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasLength(username)) {
            queryWrapper.like(SysUser::getUsername, username);
        }
        if (StringUtils.hasLength(mobile)) {
            queryWrapper.like(SysUser::getMobile, mobile);
        }
        if (StringUtils.hasLength(deptCode)) {
            queryWrapper.eq(SysUser::getDeptCode, deptCode);
        }
        if (status != null) {
            queryWrapper.eq(SysUser::getStatus, status);
        }
        queryWrapper.orderByDesc(SysUser::getId);

        IPage<SysUser> list = sysUserMapper.selectPage(page, queryWrapper);

        for (SysUser record : list.getRecords()) {
            record.setPassword(null);
        }

        return Result.ok(list);
    }

    @Override
    @Cacheable(cacheNames = {"dddd"})
    public SysUser getById(Serializable id) {
        SysUser sysUser = sysUserMapper.selectById(id);
        sysUser.setPassword(null);
        return sysUser;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(SysUser sysUser) {
        if (StringUtils.isEmpty(sysUser.getUsername())) {
            return Result.fail("请输入用户名");
        }

        List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, sysUser.getUsername()));
        if (sysUsers.size() > 0) {
            return Result.fail("用户名已存在");
        }

        sysUser.setPassword(passwordEncoder.encode("123456"));
        sysUser.setStatus(0);
        sysUserMapper.insert(sysUser);

        sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, sysUser.getUsername()));
        if (sysUsers.size() != 1) {
//            throw new Exception("查不到用户");

        }

        // 保存用户角色
        Integer userId = sysUsers.get(0).getId();
        List<Integer> roleIds = sysUser.getRoleIds();
        for (Integer roleId : roleIds) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            sysUserRoleMapper.insert(sysUserRole);
        }

        return Result.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateById(SysUser sysUser) {
        sysUser.setPassword(null);
        sysUserMapper.updateById(sysUser);

        Integer userId = sysUser.getId();
        List<Integer> roleIds = sysUser.getRoleIds();

        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        List<Integer> list = sysUserRoles.stream().map(a -> a.getRoleId()).collect(Collectors.toList());

        List<SysUserRole> deleteList = sysUserRoles.stream().filter(a -> !roleIds.contains(a.getRoleId())).collect(Collectors.toList());
        List<Integer> addList = roleIds.stream().filter(a -> !list.contains(a)).collect(Collectors.toList());

        for (SysUserRole role : deleteList) {
            sysUserRoleMapper.deleteById(role.getId());
        }

        for (Integer roleId : addList) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            sysUserRoleMapper.insert(sysUserRole);
        }

        return Result.ok();
    }

    @Override
    public Result updatePassword(UpdatePasswordReq updatePasswordReq) throws Exception {

        if (StringUtils.isEmpty(updatePasswordReq.getNewPwd()) ||
                StringUtils.isEmpty(updatePasswordReq.getOldPwd())) {
            return Result.fail("密码不能为空");
        }

        String oldPwd = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, updatePasswordReq.getOldPwd());
        String newPwd = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, updatePasswordReq.getNewPwd());

        UserJwt userJwt = Holder.USER_JWT_THREAD_LOCAL.get();
        Integer userId = userJwt.getUserId();
        SysUser sysUser = sysUserMapper.selectById(userId);

        if (!passwordEncoder.matches(oldPwd, sysUser.getPassword())) {
            return Result.fail("旧密码错误");
        }
        if (passwordEncoder.matches(oldPwd, passwordEncoder.encode(newPwd))) {
            return Result.fail("新密码不能与旧密码相同");
        }

        SysUser update = new SysUser();
        update.setId(userId);
        update.setPassword(passwordEncoder.encode(newPwd));
        sysUserMapper.updateById(update);

        return Result.ok();
    }

    @Override
    public Result deleteByIds(Set<Integer> ids) {

        for (Integer id : ids) {
            sysUserMapper.deleteById(id);
        }

        return Result.ok();
    }

    @Override
    public Result<UserInfoResp> getUserInfo(Integer userId, String username) {

        List<SysMenu> list = sysMenuMapper.selectMenuByUserId(userId);
        if (list.size() == 0) {
            return Result.fail();
        }

        ArrayList<MenuVo> menus = new ArrayList<>();
        ArrayList<String> permissions = new ArrayList<>();
        for (SysMenu sysMenu : list) {
            if (sysMenu == null) {
                continue;
            }

            if (sysMenu.getPid() == 0) {
                MenuVo menuVo = new MenuVo();
                menuVo.setId(sysMenu.getId());
                menuVo.setTitle(sysMenu.getTitle());
                menuVo.setPath(sysMenu.getPath());
                menuVo.setComponent(sysMenu.getComponent());
                menuVo.setRoute(sysMenu.getRoute());
                menuVo.setIcon(sysMenu.getIcon());
                menus.add(menuVo);
            }

            // 如果是按钮权限
            if (sysMenu.getType() == 1) {
                permissions.add(sysMenu.getPermission());
            }
        }

        for (SysMenu sysMenu : list) {
            if (sysMenu == null || sysMenu.getPid() == 0) {
                continue;
            }
            for (MenuVo menu : menus) {
                if (menu.getId() == sysMenu.getPid()) {
                    MenuVo menuVo = new MenuVo();
                    menuVo.setTitle(sysMenu.getTitle());
                    menuVo.setPath(sysMenu.getPath());
                    menuVo.setComponent(sysMenu.getComponent());
                    menuVo.setRoute(sysMenu.getRoute());
                    menuVo.setIcon(sysMenu.getIcon());
                    if (menu.getChild() == null) {
                        menu.setChild(new ArrayList<>());
                    }
                    menu.getChild().add(menuVo);
                }
            }
        }

        UserInfoResp userInfoResp = new UserInfoResp();
        userInfoResp.setMenus(menus);
        userInfoResp.setPermissions(permissions);
        userInfoResp.setUsername(username);

        return Result.ok(userInfoResp);

    }

    public static void main(String[] args) {

        System.out.println(String.format("%02d", 2));
        System.out.println(String.format("%02d", 3));

    }


}
